<% this.title = '提交记录 #' + info.submissionId %>
<% include util %>
<% include header %>
<script src="/textFit.js"></script>
<style>
.single-subtask {
    box-shadow: none !important;
}

.single-subtask > .title {
    display: none;
}

.single-subtask > .content {
    padding: 0 !important;
}

.accordion > .content > .accordion {
    margin-top: 0;
    margin-bottom: 0;
}

.accordion > .content > .accordion > .content {
    margin-top: 0;
    margin-bottom: 14px;
}

.accordion > .content > .accordion > .content > :last-child {
    margin-bottom: -10px !important;
}
</style>
<span id="submission_content">
<div class="padding" id="vueAppFuckSafari">
  <table class="ui very basic center aligned table" id="status_table">
    <thead>
      <tr>
        <th>编号</th>
        <th>题目</th>
        <th>状态</th>
        <th v-if="displayConfig.showScore">分数</th>
        <th v-if="displayConfig.showUsage">总时间</th>
        <th v-if="displayConfig.showUsage">内存</th>
        <th v-if="displayConfig.showCode">代码 / 答案文件</th>
        <th>提交者</th>
        <th>提交时间</th>
        <th v-if="showRejudge">重新评测</th>
      </tr>
    </thead>
    <tbody>
      <tr is="submission-item" v-bind:data="roughData" :config="displayConfig" :show-rejudge="showRejudge"></tr>
    </tbody>
  </table>

  <code-box :escape="false" v-bind:content="code"></code-box>
  <code-box v-if="detailResult && detailResult.compile" :escape="false" title="编译信息" v-bind:content="detailResult.compile.message"></code-box>
  <code-box v-if="detailResult" title="系统信息" :escape="true" v-bind:content="detailResult.systemMessage"></code-box>

  <div class="ui styled fluid accordion" :class="singleSubtask ? 'single-subtask' : '' "v-if="detailResult && detailResult.judge && detailResult.judge.subtasks">
    <template v-for="subtask, $index in detailResult.judge.subtasks">
      <div class="title" :class="singleSubtask ? 'active' : ''">
        <div class="ui grid">
          <div class="three wide column">
            <i class="dropdown icon"></i>
            子任务 #{{ $index + 1 }}
          </div>
          <div class="four wide column">
            <status-label :status="getSubtaskResult(subtask)"></status-label>
          </div>
          <div class="three wide column" v-if="subtask.score != null">
            得分：<span style="font-weight: normal; ">{{ Math.trunc(subtask.score) }}</span>
          </div>
        </div>
      </div>
      <div class="content" :class="singleSubtask ? 'active' : ''">
        <div class="accordion">
          <template v-for="curCase, $caseIndex in subtask.cases">
            <div class="title">
              <div class="ui grid">
                <div class="three wide column">
                    <i class="dropdown icon"></i>
                    测试点 #{{ $caseIndex + 1 }}
                </div>
                <div class="four wide column">
                  <status-label :status="getTestcaseStatus(curCase)"></status-label>
                </div>
                <template v-if="checkTestcaseOK(curCase)">
                  <div class="three wide column">
                      得分：<span style="font-weight: normal; ">{{ Math.trunc(curCase.result.scoringRate * 100) }}</span>
                  </div>
                  <div class="three wide column" v-if="curCase.result.time != null && curCase.result.time !== NaN">
                      用时：<span style="font-weight: normal; ">{{ curCase.result.time }} ms</span>
                  </div>
                  <div class="three wide column" v-if="curCase.result.memory != null && curCase.result.memory !== NaN">
                      内存：<span style="font-weight: normal; ">{{ curCase.result.memory }} KiB</span>
                  </div>
                </template>
              </div>
            </div>
              <div class="content">
                <template v-if="checkTestcaseOK(curCase)">
                  <code-box v-if="curCase.result.input" :title="'输入文件（<span style=\'font-family: monospace; \'>'+ curCase.result.input.name +'</span>）'" :content="curCase.result.input.content"></code-box>
                  <code-box v-if="curCase.result.output" :title="'答案文件（<span style=\'font-family: monospace; \'>'+ curCase.result.output.name +'</span>）'" :content="curCase.result.output.content"></code-box>
                  <code-box title="用户输出" :content="curCase.result.userOutput"></code-box>
                  <code-box title="标准错误流" :content="curCase.result.userError"></code-box>
                  <code-box title="Special Judge 信息" :content="curCase.result.spjMessage"></code-box>
                  <code-box title="系统信息" :content="curCase.result.systemMessage"></code-box>
                </template>
                <code-box title="错误信息" :content="curCase.errorMessage"></code-box>
              </div>
          </template>
        </div>
      </div>
    </template>
  </div>
</div>
<script src="//cdn.bootcss.com/vue/2.4.2/vue.js"></script>
<script src="//cdn.bootcss.com/socket.io/2.0.3/socket.io.js"></script>
<script src="//cdn.bootcss.com/jsondiffpatch/0.2.4/jsondiffpatch.js"></script>

<% include submissions_item %>

<script type="text/x-template" id="codeBoxTemplate">
    <div style="margin-top: 0px; margin-bottom: 14px; " v-if="content != null && content !== ''">
        <p v-if="title" class="transition visible">
           <strong v-html="title"></strong>
        </p>
        <div class="ui existing segment">
          <pre v-if="escape" style="margin-top: 0; margin-bottom: 0; "><code>{{ content }}</code></pre>
          <pre v-if="!escape" style="margin-top: 0; margin-bottom: 0; "><code v-html="content"></code></pre>
        </div>
    </div>
</script>

<script>
Vue.component("code-box", {
    template: "#codeBoxTemplate",
    props: ['title', 'content', 'escape'],
});
const socketUrl = <%- syzoj.utils.judgeServer('detail') %>;
const displayConfig = <%- JSON.stringify(displayConfig) %>;
const token = <%- JSON.stringify(socketToken) %>;

const TestcaseResultType = {};
(function (TestcaseResultType) {
    TestcaseResultType[TestcaseResultType["Accepted"] = 1] = "Accepted";
    TestcaseResultType[TestcaseResultType["WrongAnswer"] = 2] = "WrongAnswer";
    TestcaseResultType[TestcaseResultType["PartiallyCorrect"] = 3] = "PartiallyCorrect";
    TestcaseResultType[TestcaseResultType["MemoryLimitExceeded"] = 4] = "MemoryLimitExceeded";
    TestcaseResultType[TestcaseResultType["TimeLimitExceeded"] = 5] = "TimeLimitExceeded";
    TestcaseResultType[TestcaseResultType["OutputLimitExceeded"] = 6] = "OutputLimitExceeded";
    TestcaseResultType[TestcaseResultType["FileError"] = 7] = "FileError";
    TestcaseResultType[TestcaseResultType["RuntimeError"] = 8] = "RuntimeError";
    TestcaseResultType[TestcaseResultType["JudgementFailed"] = 9] = "JudgementFailed";
    TestcaseResultType[TestcaseResultType["InvalidInteraction"] = 10] = "InvalidInteraction";
})(TestcaseResultType);

const statusToString = {};
statusToString[TestcaseResultType.Accepted] = "Accepted";
statusToString[TestcaseResultType.WrongAnswer] = "Wrong Answer";
statusToString[TestcaseResultType.PartiallyCorrect] = "Partially Correct";
statusToString[TestcaseResultType.MemoryLimitExceeded] = "Memory Limit Exceeded";
statusToString[TestcaseResultType.TimeLimitExceeded] = "Time Limit Exceeded";
statusToString[TestcaseResultType.OutputLimitExceeded] = "Output Limit Exceeded";
statusToString[TestcaseResultType.RuntimeError] = "Runtime Error";
statusToString[TestcaseResultType.FileError] = "File Error";
statusToString[TestcaseResultType.JudgementFailed] = "Judgement Failed";
statusToString[TestcaseResultType.InvalidInteraction] = "Invalid Interaction";

const TaskStatus = {};
(function (TaskStatus) {
    TaskStatus[TaskStatus["Waiting"] = 0] = "Waiting";
    TaskStatus[TaskStatus["Running"] = 1] = "Running";
    TaskStatus[TaskStatus["Done"] = 2] = "Done";
    TaskStatus[TaskStatus["Failed"] = 3] = "Failed";
    TaskStatus[TaskStatus["Skipped"] = 4] = "Skipped";
})(TaskStatus);

const vueApp = new Vue({
  el: '#vueAppFuckSafari',
  data: {
    roughData: {
      info: <%- JSON.stringify(info) %>,
      result: <%- JSON.stringify(roughResult) %>,
      running: false,
      displayConfig: displayConfig
    },
    code: <%- JSON.stringify(code) %>,
    detailResult: <%- JSON.stringify(detailResult) %>,
    displayConfig: displayConfig,
  },
  computed: {
    singleSubtask() {
      return this.detailResult.judge.subtasks.length === 1;
    },
    showRejudge() {
      return this.displayConfig.showRejudge && (!this.roughData.running);
    }
  },
  methods: {
    getStatusString(statusCode) {
      return statusToString[statusCode];
    },
    firstNonAC(t) {
      if (t.every(function(v){ return v === TestcaseResultType.Accepted;})) {
        return TestcaseResultType.Accepted;
      } else {
        return t.find(function(r) { return r !== TestcaseResultType.Accepted;});
      }
    },
    getSubtaskResult(t) {
      if (t.cases.some(function(c){ return c.status === TaskStatus.Running;})) {
        return "Running";
      } else if (t.cases.some(function(c) { return c.status === TaskStatus.Waiting;})) {
        return "Waiting";
      } else if (t.cases.every(function(c){ return c.status === TaskStatus.Done || c.status === TaskStatus.Skipped;})) {
        return this.getStatusString(this.firstNonAC(t.cases.filter(function(c) { return c.result; })
          .map(function(c) { return c.result.type;})));
      } else {
        return "System Error";
      }
    },
    getTestcaseStatus(c) {
      if (c.status === TaskStatus.Done) {
        return this.getStatusString(c.result.type);
      } else if (c.status === TaskStatus.Waiting) {
        return "Waiting";
      } else if (c.status === TaskStatus.Running) {
        return "Running";
      } else if (c.status === TaskStatus.Skipped) {
        return "Skipped";
      } else {
        return "System Error";
      }
    },
    checkTestcaseOK(c) {
      return c.status === TaskStatus.Done;
    }
  },
  mounted() {
    $(document).ready(function(){ $('.ui.accordion').accordion()});
  },
  updated() {
    $('.ui.accordion').accordion("refresh");
  }
});
if (token != null) {
  const loadSocketIO = function () {
    let currentVersion = 0;
    const socket = io(socketUrl);
    socket.on('connect', function () {
      socket.on('start', function () {
        vueApp.roughData.running = true;
        console.log("Judge start!");
        vueApp.detailResult = {};
      });
      socket.on('update', function (p) {
        console.log("Delta: " + JSON.stringify(p));
        if (p.from === currentVersion) {
          currentVersion = p.to;
          jsondiffpatch.patch(vueApp.detailResult, p.delta);
        } else { // Some packets are dropped. Let's reset.
          socket.close();
          setTimeout(loadSocketIO, 0);
        }
      });
      socket.on('finish', function (p) {
        console.log("Judge finished");
        vueApp.roughData.running = false;
        vueApp.roughData.result = p.roughResult;
        vueApp.detailResult = p.result;
        socket.close();
      });
      socket.emit('join', token, function (data) {
        console.log("join! " + JSON.stringify(data));
        if (data && data.ok) {
          if (data.finished) {
            vueApp.roughData.result = data.roughResult;
            vueApp.detailResult = data.result || {
              systemMessage: "系统出错，请刷新后重试。"
            };
            socket.close();
          } else {
            if (data.running) {
              vueApp.roughData.running = true;
              vueApp.detailResult = data.current.content;
              currentVersion = data.current.version;
            }
          }
        } else {
          alert("ERROR: " + JSON.stringify(data));
        }
      });
    });
  };
  loadSocketIO();
}
</script>
<script>
  document.addEventListener('keydown', function (event) {
    if ((event.ctrlKey || event.metaKey) && event.key === 'a') {
      var sel = window.getSelection();
      var rg = document.createRange()
      rg.selectNodeContents(document.querySelector('code'));
      sel.removeAllRanges();
      sel.addRange(rg);
      event.preventDefault();
    }
  });
</script>
</span>
<% include footer %>
